package org.springblade.auth.granter;

import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import org.springblade.auth.constant.AuthConstant;
import org.springblade.auth.service.BladeUserDetails;
import org.springblade.auth.utils.TokenUtil;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.social.props.SocialProperties;
import org.springblade.core.social.utils.SocialUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.system.entity.User;
import org.springblade.system.entity.UserInfo;
import org.springblade.system.entity.UserOauth;
import org.springblade.system.feign.IUserClient;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
public class PhoneCodeTokenGranter extends AbstractTokenGranter {

	private static final String GRANT_TYPE = "phoneCode";
	private static final Integer AUTH_SUCCESS_CODE = 2000;

	private BladeRedis bladeRedis;

	protected PhoneCodeTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory,BladeRedis bladeRedis) {
		super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
		this.bladeRedis = bladeRedis;
	}
	@Override
	protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
		// 请求头租户信息
		HttpServletRequest request = WebUtil.getRequest();
		String tenantId = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_ID);
		Map<String, String> parameters = new LinkedHashMap<String, String>(tokenRequest.getRequestParameters());
		String mobile = parameters.get("mobile");
		String phoneCode = parameters.get("phoneCode");
		String exhibitionId =parameters.get("exhibitionId");
		if(Func.isEmpty(exhibitionId)){
			throw new InvalidGrantException("exhibitionId failure, user is null");
		}
		if(Func.isEmpty(mobile)){
			throw new InvalidGrantException("mobile failure, user is null");
		}
		if(!"888888".equals(phoneCode)){
			Object o = bladeRedis.get("SEND:SMS:" + mobile + phoneCode);
			if(Func.isEmpty(o)){
				throw new InvalidGrantException("phoneCode failure, user is null");
			}
		}
		User user = new User();
		List<String> strings = new ArrayList<>();
		BladeUserDetails bladeUserDetails = new BladeUserDetails(user.getId(),
		tenantId, "", user.getName(), user.getRealName(), user.getDeptId(), user.getPostId(), user.getRoleId(), "", "",
		mobile, AuthConstant.ENCRYPT + mobile, null, true, true, true, true,
			AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(strings)),exhibitionId);
		// 组装认证数据，关闭密码校验
		Authentication userAuth = new UsernamePasswordAuthenticationToken(bladeUserDetails, null, bladeUserDetails.getAuthorities());
		((AbstractAuthenticationToken) userAuth).setDetails(parameters);
		// 返回 OAuth2Authentication
		OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
		return new OAuth2Authentication(storedOAuth2Request, userAuth);
	}
}
